<!DOCTYPE html>
<html lang="en">

<!-- 
*author:雨宫月岚
*date：2021-1-3
-->

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>甘雨九宫格</title>
    <link rel="shortcut icon" href="sweetRain.png" type="image/x-icon">
    <style>
        .box {
            display: flex;
            justify-content: center;
        }

        ul {
            border: 4px solid #000;
            padding: 0;
            margin: 0;
            position: relative;
            display: flex;
            flex-wrap: wrap;
            max-width: 602px;
            max-height: 602px;
            width: 90vw;
            height: 90vw;
            list-style: none;
            background: radial-gradient(#444, #000 90%);
            border-radius: 5px;
            overflow: hidden;
        }

        li {
            max-width: 200px;
            max-height: 200px;
            width: calc((100% - 2px)/3);
            height: calc((100% - 2px)/3);
            background-image: url(sweetRain.png);
            background-size: 300% 300%;
            background-position: 0 0;
            border-radius: 5px;
            box-shadow: 0 0 10px #FFF inset;
            position: absolute;
            transition: all .4s;
            z-index: 2;
        }

        .default {
            z-index: 1;
            opacity: 0;
        }
    </style>
</head>

<body>
    <div class="box">
        <ul>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>
    <button onclick="reload()" style="background-color: deepskyblue;color: #FFF;font-weight: bold;">刷新重置</button>
    <address>by雨宫月岚[2021.1.27]</address>
</body>
<script>
    var items = document.querySelectorAll('li');
    //生成位置信息&背景位置信息的数组
    var infoArr = []
    var liWidth = items[0].clientWidth
    for (let i = 0; i < 3; i++) {
        for (let j = 0; j < 3; j++) {
            var group = []
            group.push(`${-j * 100}% ${-i * 100}%`);//backgroundPosition
            group.push(`${i * liWidth + i * 1}px`);//top
            group.push(`${j * liWidth + j * 1}px`);//left
            infoArr.push(group)
            // items[i*3 + j].style.backgroundPosition=`${-j*100}% ${-i*100}%`
            // items[i*3 + j].style.top = `${i*180 + i*1}px`
            // items[i*3 + j].style.left = `${j*180 + j*1}px`
        }
    }
    //使用数组对所有单元赋予相应的top、left、backgroundPosition
    for (let i = 0; i < items.length; i++) {
        items[i].style.backgroundPosition = infoArr[i][0];
        items[i].style.top = infoArr[i][1];
        items[i].style.left = infoArr[i][2];
    }
    // console.log(infoArr);
    var startDate = '', endDate = '';//设置计时变量

    // 第一步点击取出一块拼图
    pickDefault();
    function pickDefault() {
        for (let i = 0; i < items.length; i++) {
            items[i].onclick = function () {
                this.classList.add('default');
                for (let j = 0; j < items.length; j++) {
                    items[j].onclick = null;
                }
                var arr = [];//获取随机偶排序数组
                var inversionArr = [];
                do {
                    arr = getRadom();
                    inversionArr = [];//深拷贝该数组进行偶排序判断
                    for (let a = 0; a < arr.length; a++) {
                        inversionArr.push(arr[a])
                    }
                    inversionArr.splice(i, 1);//减去空缺块
                } while (getInversionNumber(inversionArr) % 2 != 0)
                console.log(i, arr, inversionArr, getInversionNumber(inversionArr));
                //第二步，打乱拼图
                resetPuzzle(arr);
                //第三步，开启移动模块
                moveMode();
                //开始计时;
                startDate = new Date();
            }
        }
    }
    function getRadom() {//【函数】获取随机数组
        var arr = [];
        while (arr.length < 9) {
            var a = Math.floor(Math.random() * 9)
            if (arr.indexOf(a) == -1) {
                arr.push(a);
            }
        }
        return arr;
    }
    function resetPuzzle(arr) {//【函数】打乱拼图
        for (let i = 0; i < items.length; i++) {
            items[i].style.top = infoArr[arr[i]][1];
            items[i].style.left = infoArr[arr[i]][2];
        }
    }
    function moveMode() {//【函数】开启移动模块
        var space = document.querySelector('.default');//获取空缺块
        var spaceSubNum = getSubNum(space);
        items = document.querySelectorAll('li');
        // console.log(isFinished());
        if (isFinished()) {//判断是否完成拼图
            setTimeout(() => {
                for (let i = 0; i < items.length; i++) {
                    items[i].onclick = null;
                }
            }, 0);
            setTimeout(function () {
                space.classList.remove("default");//延迟一秒后显示空缺块的图片
            }, 1000)
            endDate = new Date();//结束计时
            var time = endDate.getTime() - startDate.getTime()//计算时间差；
            setTimeout(function () {//延迟3秒弹框询问
                if (confirm(`恭喜完成拼图！用时【${time / 1000}s】!是否继续？`)) {
                    pickDefault()
                } else {
                    return;
                }
            }, 3000)
        }
        for (let i = 0; i < items.length; i++) {
            items[i].onclick = function () {
                var itemSubNum = getSubNum(items[i]);
                // console.log(infoArr[itemSubNum][1],infoArr[spaceSubNum][1]);
                if (itemSubNum == spaceSubNum - 3 || itemSubNum == spaceSubNum + 3) {// 空缺上下方块
                    this.style.top = infoArr[spaceSubNum][1];
                    space.style.top = infoArr[itemSubNum][1];
                    moveMode();
                }
                if (itemSubNum == spaceSubNum - 1 || itemSubNum == spaceSubNum + 1) {// 空缺左右方块
                    if(infoArr[itemSubNum][1]==infoArr[spaceSubNum][1]){//限制在同一行
                    this.style.left = infoArr[spaceSubNum][2];
                    space.style.left = infoArr[itemSubNum][2];
                    moveMode();}
                }
            }
        }
    }
    function getSubNum(element) {//获取下标
        for (let i = 0; i < infoArr.length; i++) {
            if (infoArr[i][1] == element.style.top && infoArr[i][2] == element.style.left) {
                return i;
            }
        }
    }
    function isFinished() {//是否完成拼图i
        for (var i = 0; i < items.length; i++) {//遍历items
            // console.log("坐标对比：" + items[i].style.top, infoArr[i][1], items[i].style.left, infoArr[i][2]);
            if (items[i].style.top == infoArr[i][1] &&//比较top
                items[i].style.left == infoArr[i][2]) {//比较left
                continue;//相等则跳过
            } else {
                return false;//但凡出现不等，返回false
            }
        }
        if (i >= items.length) {
            return true;//for循环执行完毕,判断全等，返回true
        }
    }
    // function showSeat() {//打印坐标
    //     var info = ''
    //     for (let i = 0; i < items.length; i++) {
    //         info += `${siteArr[i]}:(${items[siteArr[i]].style.left},${items[siteArr[i]].style.top})\n`;
    //     }
    //     console.log(info);
    // }
    function getInversionNumber(array) {//求数组逆序数
        var count = 0;
        for (let i = 0; i < array.length - 1; i++) {
            for (let j = i + 1; j < array.length; j++) {
                if (array[i] > array[j]) {
                    count++
                }
            }
        }
        return count;
    }
    // var textArr=[2, 4, 3, 1]
    // console.log(getInversionNumber(textArr)); 
    function reload() {
        window.location.reload();
    }
    window.onresize = function () {
        reload();
    }
</script>

</html>